package com.example.micro_property_springboot.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.micro_property_springboot.mapper.AssetInfoMapper;
import com.example.micro_property_springboot.pojo.AssetInfo;
import com.example.micro_property_springboot.pojo.DTO.request.AssetInfoRequest;
import com.example.micro_property_springboot.service.AssetInfoService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;

/**
 * 资产信息服务实现类
 */
@Slf4j
@Service
public class AssetInfoServiceImpl extends ServiceImpl<AssetInfoMapper, AssetInfo> implements AssetInfoService {

    @Override
    @Transactional
    public AssetInfo createAssetInfo(AssetInfoRequest request) {
        log.info("开始创建资产信息，请求参数：{}", request);

        // 验证请求参数
        validateAssetInfoRequest(request);

        // 检查资产编码是否已存在
        checkAssetCodeExists(request.getSerialNum());

        AssetInfo assetInfo = new AssetInfo();
        // 生成资产编码
        assetInfo.setAssetCode(generateAssetCode());
        assetInfo.setName(request.getName());
        assetInfo.setCategoryId(request.getCategoryId());
        assetInfo.setSpec(request.getSpec());
        assetInfo.setModel(request.getModel());
        assetInfo.setPurchaseDate(request.getPurchaseDate());
        assetInfo.setPrice(request.getPrice());
        assetInfo.setTotalPrice(request.getPrice()); // 初始总价值等于单价
        assetInfo.setSupplier(request.getSupplier());
        assetInfo.setSerialNum(request.getSerialNum());
        assetInfo.setLocation(request.getLocation());
        assetInfo.setStatus("NORMAL"); // 默认状态为正常
        assetInfo.setUserId(1L); // 默认使用人ID，实际应从认证信息获取
        assetInfo.setDeptId(1L); // 默认部门ID，实际应根据业务逻辑设置
        assetInfo.setCreateTime(LocalDateTime.now());
        assetInfo.setUpdateTime(LocalDateTime.now());

        // 保存资产信息
        save(assetInfo);
        log.info("资产信息创建成功，资产ID：{}，资产编码：{}", assetInfo.getId(), assetInfo.getAssetCode());

        return assetInfo;
    }

    @Override
    @Transactional
    public boolean updateAssetInfo(Long id, AssetInfoRequest request) {
        log.info("开始更新资产信息，资产ID：{}，请求参数：{}", id, request);

        // 验证请求参数
        validateAssetInfoRequest(request);

        AssetInfo assetInfo = getById(id);
        if (assetInfo == null) {
            log.error("资产信息不存在，资产ID：{}", id);
            throw new RuntimeException("资产信息不存在");
        }

        // 检查序列号是否被其他资产使用（排除当前资产）
        checkSerialNumExists(request.getSerialNum(), id);

        // 更新资产信息
        assetInfo.setName(request.getName());
        assetInfo.setCategoryId(request.getCategoryId());
        assetInfo.setSpec(request.getSpec());
        assetInfo.setModel(request.getModel());
        assetInfo.setPurchaseDate(request.getPurchaseDate());
        assetInfo.setPrice(request.getPrice());
        assetInfo.setSupplier(request.getSupplier());
        assetInfo.setSerialNum(request.getSerialNum());
        assetInfo.setLocation(request.getLocation());
        assetInfo.setUpdateTime(LocalDateTime.now());

        boolean result = updateById(assetInfo);
        if (result) {
            log.info("资产信息更新成功，资产ID：{}", id);
        } else {
            log.error("资产信息更新失败，资产ID：{}", id);
        }

        return result;
    }

    @Override
    @Transactional
    public boolean deleteAssetInfo(Long id) {
        log.info("开始删除资产信息，资产ID：{}", id);

        AssetInfo assetInfo = getById(id);
        if (assetInfo == null) {
            log.error("资产信息不存在，资产ID：{}", id);
            throw new RuntimeException("资产信息不存在");
        }

        // 检查资产状态，只有正常状态的资产可以删除
        if (!"NORMAL".equals(assetInfo.getStatus())) {
            log.error("只有正常状态的资产可以删除，当前状态：{}，资产ID：{}", assetInfo.getStatus(), id);
            throw new RuntimeException("只有正常状态的资产可以删除");
        }

        boolean result = removeById(id);
        if (result) {
            log.info("资产信息删除成功，资产ID：{}", id);
        } else {
            log.error("资产信息删除失败，资产ID：{}", id);
        }

        return result;
    }

    /**
     * 根据分类ID查询资产列表
     * @param categoryId 分类ID
     * @return 资产列表
     */
    public List<AssetInfo> getAssetsByCategory(Long categoryId) {
        log.info("根据分类ID查询资产列表，分类ID：{}", categoryId);

        QueryWrapper<AssetInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("category_id", categoryId);
        queryWrapper.eq("status", "NORMAL");
        queryWrapper.orderByDesc("create_time");

        List<AssetInfo> assets = list(queryWrapper);
        log.info("查询到{}个资产，分类ID：{}", assets.size(), categoryId);

        return assets;
    }

    /**
     * 根据部门ID查询资产列表
     * @param deptId 部门ID
     * @return 资产列表
     */
    public List<AssetInfo> getAssetsByDepartment(Long deptId) {
        log.info("根据部门ID查询资产列表，部门ID：{}", deptId);

        QueryWrapper<AssetInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("dept_id", deptId);
        queryWrapper.eq("status", "NORMAL");
        queryWrapper.orderByDesc("create_time");

        List<AssetInfo> assets = list(queryWrapper);
        log.info("查询到{}个资产，部门ID：{}", assets.size(), deptId);

        return assets;
    }

    /**
     * 根据状态查询资产列表
     * @param status 资产状态
     * @return 资产列表
     */
    public List<AssetInfo> getAssetsByStatus(String status) {
        log.info("根据状态查询资产列表，状态：{}", status);

        QueryWrapper<AssetInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("status", status);
        queryWrapper.orderByDesc("create_time");

        List<AssetInfo> assets = list(queryWrapper);
        log.info("查询到{}个资产，状态：{}", assets.size(), status);

        return assets;
    }

    /**
     * 验证资产信息请求参数
     * @param request 请求参数
     */
    private void validateAssetInfoRequest(AssetInfoRequest request) {
        if (request.getName() == null || request.getName().trim().isEmpty()) {
            throw new RuntimeException("资产名称不能为空");
        }

        if (request.getCategoryId() == null) {
            throw new RuntimeException("分类ID不能为空");
        }

        if (request.getSpec() == null || request.getSpec().trim().isEmpty()) {
            throw new RuntimeException("资产规格不能为空");
        }

        if (request.getModel() == null || request.getModel().trim().isEmpty()) {
            throw new RuntimeException("资产型号不能为空");
        }

        if (request.getPurchaseDate() == null) {
            throw new RuntimeException("采购日期不能为空");
        }

        if (request.getPrice() == null || request.getPrice().compareTo(java.math.BigDecimal.ZERO) <= 0) {
            throw new RuntimeException("资产价格必须大于0");
        }

        if (request.getSupplier() == null || request.getSupplier().trim().isEmpty()) {
            throw new RuntimeException("供应商不能为空");
        }

        if (request.getSerialNum() == null || request.getSerialNum().trim().isEmpty()) {
            throw new RuntimeException("序列号不能为空");
        }

        if (request.getLocation() == null || request.getLocation().trim().isEmpty()) {
            throw new RuntimeException("存放地点不能为空");
        }
    }

    /**
     * 检查资产编码是否已存在
     * @param serialNum 序列号
     */
    private void checkAssetCodeExists(String serialNum) {
        QueryWrapper<AssetInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("serial_num", serialNum);

        long count = count(queryWrapper);
        if (count > 0) {
            log.error("资产序列号已存在：{}", serialNum);
            throw new RuntimeException("资产序列号已存在");
        }
    }

    /**
     * 检查序列号是否被其他资产使用
     * @param serialNum 序列号
     * @param excludeId 排除的资产ID
     */
    private void checkSerialNumExists(String serialNum, Long excludeId) {
        QueryWrapper<AssetInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("serial_num", serialNum);
        queryWrapper.ne("id", excludeId);

        long count = count(queryWrapper);
        if (count > 0) {
            log.error("资产序列号已被其他资产使用：{}", serialNum);
            throw new RuntimeException("资产序列号已被其他资产使用");
        }
    }

    /**
     * 生成资产编码
     * @return 资产编码
     */
    private String generateAssetCode() {
        return "ASSET" + System.currentTimeMillis() + UUID.randomUUID().toString().substring(0, 4).toUpperCase();
    }
}